import numpy as np


def parse_obj_file(file_path):
    """
    手动解析OBJ文件，返回顶点、法线和索引数据

    参数:
        file_path (str): OBJ文件路径

    返回:
        tuple: (vertices, normals, indices)
        - vertices: 顶点坐标数组，形状为(N, 3)
        - normals: 顶点法线数组，形状为(N, 3)
        - indices: 面索引数组，形状为(M, 3)
    """
    # 临时存储原始数据
    raw_vertices = []
    raw_normals = []
    raw_faces = []

    with open(file_path, 'r') as f:
        for line in f:
            line = line.strip()
            if not line or line.startswith('#'):
                continue

            parts = line.split()
            if not parts:
                continue

            prefix = parts[0]
            data = parts[1:]

            # 解析顶点
            if prefix == 'v':
                vertex = list(map(float, data[:3]))
                raw_vertices.append(vertex)

            # 解析法线
            elif prefix == 'vn':
                normal = list(map(float, data[:3]))
                raw_normals.append(normal)

            # 解析面
            elif prefix == 'f':
                face = []
                for part in data:
                    # 处理顶点索引 (格式可能为 v/vt/vn 或 v//vn 或 v)
                    indices = part.split('/')
                    # 只关心顶点和法线索引
                    vertex_index = int(indices[0]) - 1  # OBJ索引从1开始
                    normal_index = int(indices[2]) - 1 if len(indices) > 2 and indices[2] else None
                    face.append((vertex_index, normal_index))
                raw_faces.append(face)

    # 处理顶点数据
    vertices = np.array(raw_vertices, dtype=np.float32)

    # 处理法线数据
    if raw_normals:
        normals = np.array(raw_normals, dtype=np.float32)
    else:
        normals = np.zeros_like(vertices)

    # 处理索引数据
    indices = []
    vertex_normal_map = {}  # 用于处理顶点-法线组合
    current_index = 0

    for face in raw_faces:
        face_indices = []
        for vertex_idx, normal_idx in face:
            # 如果法线索引不存在，使用0
            normal_idx = normal_idx if normal_idx is not None else 0

            # 创建顶点-法线组合键
            key = (vertex_idx, normal_idx)

            # 如果这个组合不存在，添加到映射表
            if key not in vertex_normal_map:
                vertex_normal_map[key] = current_index
                current_index += 1

            face_indices.append(vertex_normal_map[key])

        # OBJ文件中的面可能是多边形，这里简化为三角形
        if len(face_indices) == 3:
            indices.append(face_indices)
        elif len(face_indices) > 3:
            # 简单多边形三角剖分 (扇形)
            for i in range(1, len(face_indices) - 1):
                indices.append([face_indices[0], face_indices[i], face_indices[i + 1]])

    indices = np.array(indices, dtype=np.uint32)

    # 重新组织顶点和法线数据以匹配索引
    unique_vertices = np.zeros((len(vertex_normal_map), 3), dtype=np.float32)
    unique_normals = np.zeros((len(vertex_normal_map), 3), dtype=np.float32)

    for (vertex_idx, normal_idx), new_idx in vertex_normal_map.items():
        unique_vertices[new_idx] = vertices[vertex_idx]
        unique_normals[new_idx] = normals[normal_idx] if normal_idx < len(normals) else [0, 0, 0]

    return unique_vertices, unique_normals, indices


# 使用示例
if __name__ == "__main__":
    try:
        vertices, normals, indices = parse_obj_file("Resources/Models/Clouds/cloud.obj")
        print(f"顶点数量: {len(vertices)}")
        print(f"法线数量: {len(normals)}")
        print(f"三角形数量: {len(indices)}")

        # 打印前5个顶点、法线和索引
        print("\n前5个顶点:")
        print(vertices[:5])
        print("\n前5个法线:")
        print(normals[:5])
        print("\n前5个三角形索引:")
        print(indices[:5])

    except Exception as e:
        print(f"解析OBJ文件时出错: {e}")